/*=============================================================================
**                                  
**                      Proprietary - Copyright (C) 2013
**-----------------------------------------------------------------------------
** Supported MCUs      : <STM32F103 / MCU independent>
** Supported Compilers : <KeilC / compiler independent>
**-----------------------------------------------------------------------------
** File name         : IF_FLASH.c
**
** Module name       : IF_FLASH
**
**
** Summary: __________________________
**
**= History ===================================================================
** 1.00  22/04/2013 Cuong Chu
** - description
=============================================================================*/


/*****************************************************************************/
/* INCLUSIONS                                                                */
/*****************************************************************************/
#include <IF_FLASH.h>


/*****************************************************************************/
/* PUBLISHED INFORMATION                                                     */
/*****************************************************************************/


/*****************************************************************************/
/* DEFINITION OF CONSTANTS                                                   */
/*****************************************************************************/
#define StartAddr  ((u32)0x0803f800)
#define EndAddr    ((u32)0x0803ffff)
#define CHECK_BYTE 0x0060
/*****************************************************************************/
/* DEFINITION OF TYPES                                                       */
/*****************************************************************************/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/*****************************************************************************/
/* DEFINITION OF MACROS                                                      */
/*****************************************************************************/

/*****************************************************************************/
/* DECLARATION OF VARIABLES                                                  */
/*****************************************************************************/
static u32 Address = 0x00;
static u32 Data;
static vu32 NbrOfPage = 0x00;
static volatile FLASH_Status FLASHStatus;
static volatile TestStatus MemoryProgramStatus;
uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0;
/*****************************************************************************/
/* DECLARATION OF GLOBALES FUNCTIONS (APIs, Callbacks & MainFunctions)       */
/*****************************************************************************/
#define FLASH_PAGE_SIZE    ((uint16_t)0x800)
#define FLASH_PAGES_TO_BE_PROTECTED (FLASH_WRProt_Pages12to13 | FLASH_WRProt_Pages14to15) 
/**
   * @brief  Write App Config to internal flash 
   * @param  
                - volatile uint16_t* p : Pointer of config variable in flash
                - uint16_t SizeOfAppConfig : Size of config variable to write
   * @retval None
   */
int IF_FLASH_WriteAppConfig(volatile uint16_t* p,uint16_t SizeOfAppConfig)
{
  volatile uint16_t *temp,c;
  temp = p;
  FLASHStatus = FLASH_COMPLETE;
  MemoryProgramStatus = PASSED;
  FLASH_Unlock();  
  NbrOfPage = (EndAddr - StartAddr) / 1024;
  FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
  /* Erase the FLASH pages */
  NbrOfPage = 0;
  FLASHStatus = FLASH_ErasePage(StartAddr + (1024* NbrOfPage));
  if(FLASHStatus != FLASH_COMPLETE) {   FLASH_Lock(); return 0;}
  Address = StartAddr;
  FLASHStatus = FLASH_ProgramWord(Address,CHECK_BYTE);
  if(FLASHStatus != FLASH_COMPLETE) {   FLASH_Lock(); return 0;}
  Address = StartAddr+4;
  c = 0;
  while((c<SizeOfAppConfig) && (FLASHStatus == FLASH_COMPLETE))
  {
    Data = *p;
    FLASHStatus = FLASH_ProgramWord(Address,*p++);
    Data = *(__IO uint16_t*)Address;
    Address = Address + 4;
        c++;
  }       
  /* Check the corectness of written data */
  Address = StartAddr+4;
  c = 0;
  p = temp;
  while((c < SizeOfAppConfig) && (MemoryProgramStatus != FAILED))
  {
    Data = *p++;
    if((*(vu32*) Address) != Data)
    {
      MemoryProgramStatus = FAILED;
      return 0;
    }
    Address = Address + 4;
        c++;
  }
 FLASH_Lock();
 return 1;
}

/**
   * @brief  Read App Config from internal flash 
   * @param  
                - volatile uint16_t* p : Pointer of config variable in flash
                - uint16_t SizeOfAppConfig : Size of config variable in flash
   * @retval None
   */  
void IF_FLASH_ReadAppConfig(volatile uint16_t* p,uint16_t SizeOfAppConfig)
{
  volatile uint16_t c;  
  FLASH_Unlock();
  Address = StartAddr;
  c =  *(__IO uint16_t*)Address;
  
  Address = StartAddr+4;
  c = 0;                                                                                                                                           
  while(c<SizeOfAppConfig)
  {
        Data = *(__IO uint16_t*)Address;
        *p++ = Data;
        Address = Address + 4;
        c++;
  }
  FLASH_Lock();
  
}
